/*-
 * ============LICENSE_START=======================================================
 * SDC
 * ================================================================================
 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
 * ================================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============LICENSE_END=========================================================
 */

package org.onap.sdc.frontend.ci.tests.verificator;

import com.aventstack.extentreports.Status;
import org.onap.sdc.backend.ci.tests.datatypes.TypeHeatMetaDefinition;
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.model.ComponentInstance;
import org.openecomp.sdc.be.model.GroupInstance;
import org.openecomp.sdc.be.model.Resource;
import org.openecomp.sdc.be.model.Service;
import org.onap.sdc.frontend.ci.tests.execute.setup.SetupCDTest;
import org.onap.sdc.backend.ci.tests.tosca.datatypes.ToscaDefinition;
import org.onap.sdc.backend.ci.tests.tosca.datatypes.ToscaGroupsTopologyTemplateDefinition;
import org.onap.sdc.backend.ci.tests.tosca.datatypes.ToscaServiceGroupsMetadataDefinition;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;

public class VfModuleVerificator {

    private VfModuleVerificator() {
    }

    private static final List<String> PROPERTY_TYPES = DeploymentViewVerificator.getCurrentPropertiesWithoutIsBase(); //{"vf_module_label", "min_vf_module_instances", "max_vf_module_instances", "initial_count"};
    private static final String VF_MODULE_TYPE = "org.openecomp.groups.VfModule";

    /**
     * compare number of groups from HEAT.meta file vs TOSCA yaml groups generated by ASDC
     *
     * @param listTypeHeatMetaDefinition - java object created from HEAT.meta file
     * @param toscaDefinition            - java object created from TOSCA yaml
     */
    public static void compareNumberOfVfModules(List<TypeHeatMetaDefinition> listTypeHeatMetaDefinition, ToscaDefinition toscaDefinition) {

        int heatMetaGroupCount = 0;
        int toscaDefinitionGroupCount = 0;
        for (TypeHeatMetaDefinition typeHeatMetaDefinition : listTypeHeatMetaDefinition) {
            if (!typeHeatMetaDefinition.getTypeName().equals("artifacts")) {
                heatMetaGroupCount = typeHeatMetaDefinition.getGroupHeatMetaDefinition().size();
            }
        }
        toscaDefinitionGroupCount = toscaDefinition.getTopology_template().getGroups().size();
        assertEquals("Expected num of groups in HEAT.meta file is " + heatMetaGroupCount + ", but was in TOSCA yaml file " + toscaDefinitionGroupCount, heatMetaGroupCount, toscaDefinitionGroupCount);
    }

    /**
     * check group structure and "metadata" parameters vs data on the service object
     *
     * @param toscaDefinition
     */
    public static void verifyGroupMetadata(ToscaDefinition toscaDefinition, Service service) {

        Map<String, ToscaGroupsTopologyTemplateDefinition> groups = toscaDefinition.getTopology_template().getGroups();
        for (Map.Entry<String, ToscaGroupsTopologyTemplateDefinition> groupTopologyTemplateDefinition : groups.entrySet()) {
            String key = groupTopologyTemplateDefinition.getKey();
            GroupInstance groupInstanceObject = getGroupInstanceByKey(key, service);
            ToscaServiceGroupsMetadataDefinition metadata = groupTopologyTemplateDefinition.getValue();
            assertNotNull("groupInstanceObject is null", groupInstanceObject);
            assertTrue("expected vfModuleModelName " + groupInstanceObject.getGroupName() + ", actual " + metadata.getVfModuleModelName(), groupInstanceObject.getGroupName().equals(metadata.getVfModuleModelName()));
            assertTrue("expected vfModuleModelInvariantUUID " + groupInstanceObject.getInvariantUUID() + ", actual " + metadata.getVfModuleModelInvariantUUID(), groupInstanceObject.getInvariantUUID().equals(metadata.getVfModuleModelInvariantUUID()));
            assertTrue("expected vfModuleModelCustomizationUUID " + groupInstanceObject.getCustomizationUUID() + ", actual " + metadata.getVfModuleModelCustomizationUUID(), groupInstanceObject.getCustomizationUUID().equals(metadata.getVfModuleModelCustomizationUUID()));
            assertTrue("expected vfModuleModelUUID " + groupInstanceObject.getGroupUUID() + ", actual " + metadata.getVfModuleModelUUID(), groupInstanceObject.getGroupUUID().equals(metadata.getVfModuleModelUUID()));
            assertTrue("expected vfModuleModelVersion " + groupInstanceObject.getVersion() + ", actual " + metadata.getVfModuleModelVersion(), groupInstanceObject.getVersion().equals(metadata.getVfModuleModelVersion()));
        }
    }


    /**
     * @param key
     * @param service
     * @return
     */
    public static GroupInstance getGroupInstanceByKey(String key, Service service) {
        for (ComponentInstance componentInstance : service.getComponentInstances()) {
            for (GroupInstance groupInstance : componentInstance.getGroupInstances()) {
                if (key.equals(groupInstance.getName())) {
                    return groupInstance;
                }
            }
        }
        return null;
    }

    public static void validateSpecificModulePropertiesFromRequest(Resource resource) {
        List<List<PropertyDataDefinition>> allProperties = resource.getGroups().stream().
                filter(e -> e.getType().equals(VF_MODULE_TYPE)).
                map(e -> e.getProperties()).
                collect(Collectors.toList());
        for (String propertyType : PROPERTY_TYPES) {
            int numberOfTypes = getPropertyType(allProperties, propertyType).size();
            SetupCDTest.getExtendTest().log(Status.INFO, String.format("Validating VF property %s exist, Expected: %s, Actual: %s  ", propertyType, allProperties.size(), numberOfTypes));
            assertTrue(numberOfTypes == allProperties.size());
        }
    }

    public static List<PropertyDataDefinition> getPropertyType(List<List<PropertyDataDefinition>> allProperties, String propertyType) {
        return allProperties.stream().
                flatMap(List::stream).
                filter(e -> e.getName().equals(propertyType)).
                collect(Collectors.toList());
    }

    public static void validateSpecificModulePropertiesFromFile(ToscaDefinition toscaDefinition) {
        List<ToscaGroupsTopologyTemplateDefinition> vfModules = toscaDefinition.
                getTopology_template().getGroups().values().stream().
                filter(e -> e.getType().equals(VF_MODULE_TYPE)).
                collect(Collectors.toList());
        for (String propertyType : PROPERTY_TYPES) {
            int numberOfTypes = (int) vfModules.stream().
                    // Get all declared fields from class ToscaGroupPropertyDefinition, collect them to List and check that current property exist and declared class
                            filter(e -> Arrays.asList(e.getProperties().getClass().getDeclaredFields()).stream().
                            map(p -> p.getName()).
                            collect(Collectors.toList()).
                            contains(propertyType)
                    ).
                            collect(Collectors.toList()).
                            size();
            SetupCDTest.getExtendTest().log(Status.INFO, String.format("Validating VF property %s exist, Expected: %s, Actual: %s  ", propertyType, vfModules.size(), numberOfTypes));
            assertTrue(numberOfTypes == vfModules.size());
        }
    }

    public static String getTemplateFilenname(String pathToCsar) {
        File csarFile = new File(pathToCsar);
        String templateFileName = csarFile.getName().replaceAll("-csar.csar", "-template.yml");
        return templateFileName;
    }

}
